#pragma once
#include <string>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <cstring>
// 词法分析

enum Token
{
    Token_STRING , //（字符串字面量）
    Token_INTNUMBER,//（整型数字字面量）
    Token_FLOATNUMBER,//(浮点数型数字字面量)
    Token_NULL,//（null）
    Token_START_ARRAY,//（[）
    Token_END_ARRAY,//（]）
    Token_START_OBJ,//（{）
    Token_END_OBJ,//（}）
    Token_COMMA,//（,）
    Token_COLON,//（:）
    Token_BOOLEAN,//（true或者false）
    Token_END_DOC,//（表示JSON数据的结束）
};

extern char currChar ; //当前 正在解析的字符
extern FILE * fp;
extern char * sourceFileName ;

extern Token currToken;
extern char * currString;
extern int currIntNumber;
extern float currFloatNumber;
extern bool currBoolValue;

#define MAX_STRING_LEN 10000


//函数 

bool isDigit(char ch)
{
    return ch>='0' && ch <='9';
}


char getNextChar()
{
    if(!feof(fp))
    {
        currChar = fgetc(fp);
        return currChar;
    } 
    return -1; 
}
//跳过 空白部分,换行符
void skipWitheSpace()
{
    while(currChar == ' ' || currChar == '\n')
        getNextChar();
}
/* 
    解析字符串
    currChar  = " ;
    "abduefdeowjoixsc"

    暂时不考虑 转义
*/
void parseString()
{
    bool inString =false;
    int strLen = 0;
    char temp_string[MAX_STRING_LEN];

    if(currChar == '"')
    {
       inString = true;
       getNextChar();
       while(currChar != '"')
       {
           temp_string[strLen] = currChar;
           strLen ++;
           getNextChar();
       } 
       temp_string[strLen] ='\0';
    }
    char * heap_string = (char*) malloc(sizeof(char) *(strLen + 1));
    strcpy(heap_string,temp_string);
    
    heap_string[strLen] = '\0';
    //printf("%s",heap_string);
    currToken = Token_STRING;
    currString =  heap_string;

    
}

/* 
    解析数字
    currChar  = 0-9 ;
    123124
    0.234325

    暂时 只考虑 10进制
*/
void parseNumber()
{
    int tempIntValue =0;
    float tempFloatValue = 0;
    while(isDigit(currChar))
    {
        tempIntValue = tempIntValue *10 + int(currChar-'0');
        getNextChar();
    }
    if(currChar == '.')  //浮点数
    { 
        int powerIndex = 1;
        getNextChar();
        while(isDigit(currChar))
        {
            tempFloatValue = tempFloatValue  + float(currChar-'0')/pow(10,powerIndex);
            powerIndex ++;
            getNextChar();
        }
        currToken = Token_FLOATNUMBER;
        currFloatNumber =(float)tempIntValue  + tempFloatValue;
        return ;
    }
    else  // 整数
    {
        currToken = Token_INTNUMBER;
        currIntNumber = tempIntValue;
        return ;
    }
}

/* 
    解析 ident

    currChar  = t  || f ;
    true
    fasle
*/
void parseIdent()
{
    int identLen =0;
    //char pString[7] ;
    switch (currChar)
    {     ///fasle
        case 'f':
        {
            //pString[identLen] = currChar;
            identLen ++;
            while(identLen <= 5)
            {
                getNextChar();
                identLen++;
            }
            currToken = Token_BOOLEAN;
            currBoolValue = false;
            break;
        }
        //true
        case 't':
        {
            identLen ++;
            while(identLen <= 4)
            {
                getNextChar();
                identLen++;
            }
            currToken = Token_BOOLEAN;
            currBoolValue = true;
            break;
        }
    }
}


void getToken()
{
    skipWitheSpace();
    switch (currChar)
    {
        case -1:
        {
            currToken = Token_END_DOC;
            break;
        }
        case '{':
        {
            getNextChar();
            currToken = Token_START_OBJ;
            break;
        }
        case '}':
        {
            getNextChar();
            currToken = Token_END_OBJ;
            break;
        }

        case '[':
        {
            getNextChar();
            currToken = Token_START_ARRAY;
            break;
        }

        case ']':
        {
            getNextChar();
            currToken = Token_END_ARRAY;
            break;
        }

        //Token_COMMA,//（,）
        case ',':
        {
            getNextChar();
            currToken = Token_COMMA;
            break;
        }
        //Token_COLON,//（:）
        case ':':
        {
            getNextChar();
            currToken =  Token_COLON;
            break;
        }
        //Token_STRING
        case '"':
        {
            parseString();
            currToken =  Token_STRING;
            getNextChar();
            break;
        }

        //解析 true false
        case 't':
        case 'f':
        {
            parseIdent();
            break;
        }

        case '0':case '1':case '2':case '3':case '4':
        case '5':case '6':case '7':case '8':case '9':
        {
            parseNumber();
            break;
        }
        default:
        {
            std::cout<<"undefined char"<<std::endl;
            exit(0);
        }
    }

}





// int test()
// {
//     sourceFileName =(char*) "test.json";
//     fp = fopen(sourceFileName,"r");
//     // read(fp,&currChar,1);
//     // cout<<currChar<<endl;
//     getNextChar();
//     getToken();
//     while(currToken != Token_END_DOC)
//     {
//          switch (currToken)
//         {
            
//             case Token_START_OBJ:
//             {
//                 cout<< '{'<<endl;
//                 break;
//             }
//             case Token_END_OBJ:
//             {
//                 cout<< '}'<<endl;
//                 break;
//             }
//             case Token_START_ARRAY:
//             {
//                 cout<< '['<<endl;
//                 break;
//             }

//             case Token_END_ARRAY:
//             {
//                 cout<< ']'<<endl;
//                 break;
//             }

//             //Token_COMMA,//（,）
//             case Token_COMMA:
//             {
//                 cout<< ','<<endl;
//                 break;
//             }
//             //Token_COLON,//（:）
//             case Token_COLON:
//             {
//                 cout<< ';'<<endl;
//                 break;
//             }
//             //Token_STRING
//             case Token_STRING:
//             {
//                 printf("%s\n",currString);
//                 break;
//             }

//             //解析 true false
//             case Token_BOOLEAN:
//             {
//                 cout<<currBoolValue<<endl;
//                 break;
//             }

//             case Token_INTNUMBER:
//             {
//             cout<<currIntNumber<<endl;
//                 break;
//             }
//             case Token_FLOATNUMBER:
//             {
//             cout<<currFloatNumber<<endl;
//                 break;
//             }
//         }
//     }
//     return 0;
// }